package com.megvii.koala.tv.video;

import android.content.res.Configuration;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.ViewGroup;
import android.view.Window;

import com.megvii.corelib.util.ScreenUtil;

import org.videolan.libvlc.IVLCVout;
import org.videolan.libvlc.LibVLC;
import org.videolan.libvlc.Media;
import org.videolan.libvlc.MediaPlayer;

import java.util.ArrayList;

public class VideoManager implements VideoManagerInterface {
    private boolean isVideoInit;

    private boolean isTcpMode = false;      //是否是TCP传输模式

    private Window window;

    private SurfaceView surfaceView = null;

    private SurfaceHolder surfaceHolder = null;

    private LibVLC libVLC = null;

    private MediaPlayer mediaPlayer = null;

    private Thread fixingThread;

    private VLCCallBacks vlcCallBacks;

    private String videoUrl;

    private VideoManagerVLCListener listener;

    private int videoWidth;

    private int videoHeight;

    private int playerState;

    private MediaPlayerState[] mediaPlayerStates;

    private Handler mainHandler;

    private static Uri UriFromMrl(String mrl) {
        char[] array = mrl.toCharArray();
        StringBuilder sb = new StringBuilder(array.length);

        for (int i = 0; i < array.length; ++i) {
            char c = array[i];
            if (c == 37 && array.length - i >= 3) {
                try {
                    int hex = Integer.parseInt(new String(array, i + 1, 2), 16);
                    if ("!\'()*".indexOf(hex) != -1) {
                        sb.append((char) hex);
                        i += 2;
                        continue;
                    }
                } catch (NumberFormatException var6) {
                    var6.printStackTrace();
                }
            }
            sb.append(c);
        }
        return Uri.parse(sb.toString());
    }

    public int getVideoWidth() {
        return videoWidth;
    }

    public int getVideoHeight() {
        return videoHeight;
    }

    public boolean init(final Window window, final SurfaceView surfaceView) {
        if (isVideoInit) {
            return false;
        }
        mainHandler = new Handler(Looper.getMainLooper());
        LibVLC.setOnNativeCrashListener(new LibVLC.OnNativeCrashListener() {
            @Override
            public void onNativeCrash() {
                Log.d("vlc", "VideoManager vlc crashed");
                release();
                init(window, surfaceView);
                restartPlay();
                if (listener != null) {
                    listener.onVLCCrash();
                }
            }
        });
        this.window = window;
        this.surfaceView = surfaceView;
        this.surfaceHolder = surfaceView.getHolder();

        try {
            vlcCallBacks = new VLCCallBacks();
            ArrayList<String> options = new ArrayList<String>();
            //options.add("--subsdec-encoding <encoding>");
            //            options.add("--aout=opensles");
            options.add("--network-caching=500");
            options.add("--rtsp-caching=500");
            //options.add("-q");          //安静模式
//            options.add("--no-plugins-cache");
            //            options.add("--audio-time-stretch"); // time stretching
            options.add("-vvv"); // verbosity
            libVLC = new LibVLC(options);
            surfaceHolder.setKeepScreenOn(true);
            mediaPlayer = new MediaPlayer(libVLC);
            mediaPlayer.setEventListener(vlcCallBacks);
            createFixThread();
            synchronized (libVLC) {
                isVideoInit = true;
                try {
                    notify();
                } catch (IllegalMonitorStateException e) {
                    e.printStackTrace();
                }
            }
            Log.d("vlc", "VideoManager inited");
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    private void createFixThread() {
        fixingThread = new Thread() {
            public void run() {
                try {
                    while (!interrupted()) {
                        sleep(10 * 60 * 1000);
                        restartPlay();
                    }
                } catch (InterruptedException e) {
                    //此处做输出，看线程何时退出
                    e.printStackTrace();
                }
            }
        };
        fixingThread.start();
    }

    public void release() {
        if (fixingThread != null) {
            fixingThread.interrupt();
            try {
                fixingThread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        fixingThread = null;
        if (mediaPlayer != null) {
            try {
                mediaPlayer.stop();
            } catch (Exception e) {
                e.printStackTrace();
            }
            try {
                final IVLCVout vout = mediaPlayer.getVLCVout();
                vout.removeCallback(vlcCallBacks);
                vout.detachViews();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        mediaPlayer = null;
        if (libVLC != null) {
            try {
                libVLC.release();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        libVLC = null;
        surfaceView = null;
        surfaceHolder = null;
        isVideoInit = false;
    }

    private void reInit() {
        isVideoInit = false;
        init(this.window, this.surfaceView);
    }

    public void restartPlay() {
        if (videoUrl == null) {
            return;
        }
        new Thread() {
            public void run() {
                synchronized (libVLC) {
                    if (!isVideoInit) {
                        try {
                            wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
                try {
                    Log.d("vlc", "VideoManager play " + videoUrl);
                    mediaPlayer.stop();
                    final IVLCVout vout = mediaPlayer.getVLCVout();
                    vout.detachViews();
                    vout.setVideoView(surfaceView);
                    vout.addCallback(vlcCallBacks);
                    vout.attachViews();
                    //                    Uri uri = AndroidUtil.LocationToUri(videoUrl);
                    if (!videoUrl.startsWith("/")) {
                        //网络路径，判断是否是TCP模式的RTSP
                        if (videoUrl.indexOf("rtspt") != -1) {
                            //TCP模式的
                            videoUrl = videoUrl.replace("rtspt", "rtsp");
                            isTcpMode = true;

                            //重新初始化
//                            reInit();
                        }
                        Uri uri = UriFromMrl(videoUrl);
                        Media media = new Media(libVLC, uri);
                        mediaPlayer.setMedia(media);
                        //TODO fuck vlc android！这个vlc-android-sdk-1.9.0的Media的setHWDecoderEnabled里还带写死network-caching的，靠
                        //TODO 而且会在mediaplayer.setMedia里被调用到
                        //TODO 所以要把media.addOption()下载setMedia后边！
                        //TODO fuck vlc android again！
                        media.addOption(":network-caching=500");
                        if (isTcpMode) {
                            media.addOption(":rtsp-tcp");
                        }
                    } else {
                        Media media = new Media(libVLC, videoUrl);
                        mediaPlayer.setMedia(media);
                        media.addOption(":network-caching=500");
                    }
                    mediaPlayer.play();
                } catch (Exception e) {
                    mainHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            if (listener != null) {
                                listener.onPlayVideoFailed(videoUrl);
                            }
                        }
                    });
                    e.printStackTrace();
                }
            }
        }.start();
    }

    public void play(String url) {
        this.videoUrl = url;
        restartPlay();
    }

    @Override
    public void clearSrc() {
        this.videoUrl = null;
    }

    @Override
    public void stop() {
        if (mediaPlayer.isPlaying())         //修改为如果正在播放停止播放。
            mediaPlayer.stop();
    }

    public MediaPlayerState getPlayerState() {
        if (mediaPlayer != null) {
            if (mediaPlayerStates == null) {
                mediaPlayerStates = MediaPlayerState.values();
            }
            playerState = mediaPlayer.getPlayerState();
            if (playerState >= 0 && playerState < mediaPlayerStates.length) {
                return mediaPlayerStates[playerState];
            } else {
                return MediaPlayerState.ERROR;
            }
        } else {
            return MediaPlayerState.IDLE_CLOSE;
        }
    }

    public void setSize(int width, int height) {
        if (width * height <= 1) {
            return;
        }

        if (surfaceHolder == null || surfaceView == null) {
            return;
        }

        this.videoWidth = width;
        this.videoHeight = height;

        // get screen size
        int w = ScreenUtil.getInstance().screenWidth;
        int h = ScreenUtil.getInstance().screenHeight;

        // getWindow().getDecorView() doesn't always take orientation into
        // account, we have to correct the values
        boolean isPortrait = window.getContext().getResources()
                .getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
        if (w > h && isPortrait || w < h && !isPortrait) {
            int i = w;
            w = h;
            h = i;
        }

        float videoAR = (float) width / (float) height;
        float screenAR = (float) w / (float) h;

        if (screenAR < videoAR) {
            h = (int) (w / videoAR);
        } else {
            w = (int) (h * videoAR);
        }

        // force surface buffer size
        surfaceHolder.setFixedSize(width, height);

        // set display size
        ViewGroup.LayoutParams lp = surfaceView.getLayoutParams();
        lp.width = w;
        lp.height = h;
        surfaceView.setLayoutParams(lp);
        surfaceView.invalidate();
    }

    @Override
    public int getVideoCurrentTime() {
        return 0;
    }

    @Override
    public int getVideoDuration() {
        return 0;
    }

    @Override
    public void setListener(VideoManagerListener listener) {

    }

    public void setListener(VideoManagerVLCListener listener) {
        this.listener = listener;
    }

    public enum MediaPlayerState {
        IDLE_CLOSE,
        OPENING,
        BUFERRING,
        PLAYING,
        PAUSED,
        STOPPING,
        ENDED,
        ERROR,
    }

    public interface VideoManagerVLCListener {
        public void onVLCCrash();

        public void onHardwareAccelerationError();

        public void onPlayVideoFailed(String url);
    }

    public class VLCCallBacks implements IVLCVout.Callback, MediaPlayer.EventListener {
        @Override
        public void onNewLayout(IVLCVout vout, int width, int height, int visibleWidth,
                                int visibleHeight, int sarNum, int sarDen) {
            if (width * height == 0) {
                return;
            }
            setSize(width, height);
        }

        @Override
        public void onSurfacesCreated(IVLCVout ivlcVout) {
            try {
//                ivlcVout.setVideoView(surfaceView);
//                ivlcVout.addCallback(vlcCallBacks);
//                ivlcVout.attachViews();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onSurfacesDestroyed(IVLCVout ivlcVout) {

        }

        @Override
        public void onHardwareAccelerationError(IVLCVout ivlcVout) {
            //release();
            if (listener != null) {
                listener.onHardwareAccelerationError();
            }
        }

        @Override
        public void onEvent(MediaPlayer.Event event) {
            MediaPlayerState state = getPlayerState();
            switch (event.type) {
                case MediaPlayer.Event.EndReached:
                    //                    showAlertDialog("视频到达末尾" + state);
                    //reInitAndPlay();
                    break;
                case MediaPlayer.Event.Playing:
                    //                    showAlertDialog("视频正在播放" + state);
                    break;
                case MediaPlayer.Event.Paused:
                    //                    showAlertDialog("视频暂停" + state);
                    break;
                case MediaPlayer.Event.Stopped:
                    //                    showAlertDialog("视频停止 " + state);
                    if (state == MediaPlayerState.ERROR || state == MediaPlayerState.ENDED) {
                        //                        VideoUtil.this.delayRestartPlay();
                    }
                    break;
                default:
                    break;
            }
        }
    }
}